package btcdemo.btcdemo.controller;

import btcdemo.btcdemo.model.*;
import btcdemo.btcdemo.security.IdGenUtils;
import btcdemo.btcdemo.security.Sha256Utils;
import com.alibaba.fastjson.JSON;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

/**
 * 初始化创世区块已经在启动类中完成
 */
@RestController
public class BlockController {


    @GetMapping("block/wallet/gen")
    public Object genWallet(){
        Wallet wallet = Wallet.generateWallet();
        Wallet.walletMap.put(wallet.getAddress(),wallet);
        return wallet.getAddress();
    }


    /* 挖矿测试 */
    @GetMapping("block/mining/{address}")
    public Object mining(@PathVariable String address){
        if (address==null||address.trim().length()<=0){
            return "请输入钱包地址！";
        }


        Wallet wallet = Wallet.walletMap.get(address);

        if (wallet==null){
            return "账户不存在！";
        }

        //创建挖矿 系统奖励的交易
        List<Transaction> txs = new ArrayList<>();
        TransactionInput transactionInput = TransactionInput.getSystemTransactionInput();
        TransactionOutput transactionOutput = new TransactionOutput(Transaction.SYSTEM_AWARD, wallet.getPublicKey());
        Transaction sysTx = new Transaction(IdGenUtils.genId(),transactionInput, transactionOutput);
        txs.add(sysTx);

        // 获取区块链的最后一个区块，并开始解数学难题
        Block lastBlock = Block.blockList.get(Block.blockList.size()-1);

        //定义初始工作量
        int nonce = 1;
        //定义本次挖矿的哈希值
        String hash;
        while(true){
            hash = Sha256Utils.sha256(lastBlock.getHash() + JSON.toJSONString(txs) + nonce);
            if (hash.startsWith("0000")) {
                System.out.println("=====计算结果正确，计算次数为：" +nonce+ ",hash:" + hash);
                break;
            }
            nonce++;
        }

        // 解出后打包交易，然后加入到区块中
        Block newBlock = new Block(lastBlock.getIndex() + 1, System.currentTimeMillis(), txs, nonce, lastBlock.getHash(), hash);
        Block.blockList.add(newBlock);
        return Block.blockList;
    }

}
